#include <android/bitmap.h>
#include <android/log.h>
#include <jni.h>
#include <string>
#include <vector>
#include "new.id.h"
#include <sys/time.h>
#include <unistd.h>
#include <opencv2/opencv.hpp>
#include <fstream>
//NCNN
#include "net.h"

using namespace cv;



//NCNN调用
static std::vector<unsigned char> MTCNN_param;
static std::vector<unsigned char> MTCNN_bin;
static ncnn::Net MTCNN;

//时间计算
static struct timeval tv_begin;
static struct timeval tv_end;
static double elasped;

static void bench_start()
{
    gettimeofday(&tv_begin, NULL);
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "start");
}

static void bench_end(const char* comment)
{
    gettimeofday(&tv_end, NULL);
    elasped = ((tv_end.tv_sec - tv_begin.tv_sec) * 1000000.0f + tv_end.tv_usec - tv_begin.tv_usec) / 1000.0f;
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "%.2fms   %s", elasped, comment);
}

//检测类
class Detector {
public:
    Detector(ncnn::Net MTCNN);
    float Detect(const Mat& img);

private:
    ncnn::Net MTCNN;
};

Detector::Detector(ncnn::Net MTCNN2){
    MTCNN = MTCNN2;
}

float Detector::Detect(const Mat& image){
    // invert to RGB color space and float type
    Mat bgr,resized,converted,normed;
    image.convertTo(bgr,CV_32FC3);
    bgr = bgr.t();

    resize(bgr,resized,Size(227,227));

    int height = resized.rows;
    int width  = resized.cols;

    ncnn::Extractor ex = MTCNN.create_extractor();
    ex.set_light_mode(true);
    ex.set_num_threads(4);

    resized.convertTo(converted, CV_32FC3);
    //normalize(converted, normed, 1.0, 0.0, NORM_INF);



    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "normed.height%d", height);
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "normed.width %d", width);

    //模型输入

    ncnn::Mat in = ncnn::Mat::from_pixels((const unsigned char*)converted.data, ncnn::Mat::PIXEL_BGR, width, height);
    const float mean_vals[3] = {104.f, 117.f, 123.f};



    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "1111111in.w %d", in.w);
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "1111111in.h %d", in.h);
    in.substract_mean_normalize(mean_vals, 0);

    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "in.w %d", in.w);
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "in.h %d", in.h);



    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "conventing");
    ex.input(new_param_id::BLOB_data, in);
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "a$$##");

    //模型输出
    ncnn::Mat reg;
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "^^^^^^");

//    ex.extract(new_param_id::BLOB_reg, reg);
    ncnn::Mat confidence;
    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "&&&&&&^^");

    ex.extract(new_param_id::BLOB_prob, confidence);

    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "after output");

    return 0.0F;
}

//接口
extern "C" {

//改名字/////////////////////////////////////////////////////
JNIEXPORT jfloat JNICALL Java_com_ckt_eirot_opencv4jni_Grayprocess_grayprocess(
        JNIEnv *env,
        jobject thiz,
        jbyteArray param,
        jbyteArray bin,
        jintArray buf,
        jint w,
        jint h)
{
//    bench_start();
//
    jboolean ptfalse = false;
    jint *srcBuf = env->GetIntArrayElements(buf, &ptfalse);

    int size = w * h;

    Mat image(h, w, CV_8UC4, (unsigned char*) srcBuf);

    ncnn::Net MTCNN;

    //初始化模型，来自demo
    {
        int len = env->GetArrayLength(param);
        MTCNN_param.resize(len);
        env->GetByteArrayRegion(param, 0, len, (jbyte *) MTCNN_param.data());
        int ret = MTCNN.load_param(MTCNN_param.data());
        __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "load_param %d %d", ret, len);
    }
    {
        int len = env->GetArrayLength(bin);
        MTCNN_bin.resize(len);
        env->GetByteArrayRegion(bin, 0, len, (jbyte*)MTCNN_bin.data());
        int ret = MTCNN.load_model(MTCNN_bin.data());
        __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "load_model %d %d", ret, len);
    }

    Detector detector(MTCNN);

    __android_log_print(ANDROID_LOG_DEBUG, "MTCNN", "detect %d x %d", image.rows, image.cols);
//    float confidence = detector.Detect(image);
    detector.Detect(image);

    bench_end("end!!!!!!!!!!!!!!!!!!!!!!!");


    return 0.0;




}

}



